// Copyright (c) 2024 Go-Frame-Lite
// Go-Frame-Lite is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//         http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.

package gerror

import (
	"github.com/gin-gonic/gin"
)

// GinContext 包装Gin上下文，提供标准错误处理
// 类似于GF框架的ghttp.Request
type GinContext struct {
	*gin.Context
	ShowDetail bool // 是否显示详细错误信息
}

// NewGinContext 创建新的Gin上下文包装器
func NewGinContext(c *gin.Context, showDetail bool) *GinContext {
	return &GinContext{
		Context:    c,
		ShowDetail: showDetail,
	}
}

// Success 返回成功响应
// 类似于GF框架的ghttp.Response.Success
func (c *GinContext) Success(data interface{}) {
	resp := Success(data)
	c.JSON(HTTPStatusFromCode(resp.Code), resp)
}

// Error 返回错误响应
// 类似于GF框架的ghttp.Response.Error
func (c *GinContext) Error(code int, message ...string) {
	resp := Error(code, message...)
	c.JSON(HTTPStatusFromCode(resp.Code), resp)
}

// FromError 从错误返回响应
// 类似于GF框架的ghttp.Response.FromError
func (c *GinContext) FromError(err error) {
	resp := FromError(err, c.ShowDetail)
	c.JSON(HTTPStatusFromCode(resp.Code), resp)
}

// GinHandlerFunc Gin处理函数类型
// 类似于GF框架的ghttp.HandlerFunc
type GinHandlerFunc func(*GinContext) error

// GinHandler 创建Gin中间件，提供标准错误处理
// 类似于GF框架的ghttp.MiddlewareHandlerResponse
func GinHandler(handler GinHandlerFunc, showDetail bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		ctx := NewGinContext(c, showDetail)
		
		if err := handler(ctx); err != nil {
			ctx.FromError(err)
		}
	}
}

// GinRecovery Gin恢复中间件，捕获panic并返回标准错误
// 类似于GF框架的ghttp.MiddlewareRecover
func GinRecovery(showDetail bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				var panicErr error
				if e, ok := err.(error); ok {
					panicErr = Wrap(e, CodeInternalError, "内部服务器错误")
				} else {
					panicErr = New(CodeInternalError, "内部服务器错误")
				}
				
				ctx := NewGinContext(c, showDetail)
				ctx.FromError(panicErr)
				
				// 阻止继续处理
				c.Abort()
			}
		}()
		
		c.Next()
	}
}

// GinBindAndValidate 绑定并验证请求参数，返回标准错误
// 类似于GF框架的ghttp.Request.Bind
func (c *GinContext) GinBindAndValidate(obj interface{}) error {
	if err := c.ShouldBind(obj); err != nil {
		return Wrap(err, CodeInvalidParameter, "参数绑定失败")
	}
	
	// 这里可以集成验证器，例如使用go-playground/validator
	// if err := validate.Struct(obj); err != nil {
	//     return Wrap(err, CodeInvalidParameter, "参数验证失败")
	// }
	
	return nil
}

// GinGetParam 获取URL参数，如果不存在返回标准错误
// 类似于GF框架的ghttp.Request.Get
func (c *GinContext) GinGetParam(key string) (string, error) {
	value := c.Param(key)
	if value == "" {
		return "", New(CodeMissingParameter, "缺少必要参数: "+key)
	}
	return value, nil
}

// GinGetQuery 获取查询参数，如果不存在返回标准错误
// 类似于GF框架的ghttp.Request.GetQuery
func (c *GinContext) GinGetQuery(key string) (string, error) {
	value := c.Query(key)
	if value == "" {
		return "", New(CodeMissingParameter, "缺少查询参数: "+key)
	}
	return value, nil
}

// GinGetHeader 获取请求头，如果不存在返回标准错误
// 类似于GF框架的ghttp.Request.GetHeader
func (c *GinContext) GinGetHeader(key string) (string, error) {
	value := c.GetHeader(key)
	if value == "" {
		return "", New(CodeMissingParameter, "缺少请求头: "+key)
	}
	return value, nil
}

// Example usage:
// 
// router.GET("/api/users/:id", errors.GinHandler(func(c *errors.GinContext) error {
//     id, err := c.GinGetParam("id")
//     if err != nil {
//         return err
//     }
//     
//     user, err := getUserByID(id)
//     if err != nil {
//         return errors.Wrap(err, errors.CodeDataNotFound, "用户不存在")
//     }
//     
//     c.Success(user)
//     return nil
// }, true))